package strangeattractor.core;

import java.awt.Color;
import java.awt.Point;

public class DefaultExposureScheme implements ColorScheme {
	//The default Exposure Scheme uses the amount of points represented on a single pixel to calculate the color on this point.
	//No points results in background color. The more points are on the pixel, the more it goes towards the endpoint color.

	public Color initialColor = Color.black;
	public Color endpoint = Color.blue;

	private Viewpoint camera;

	public int[][] exposures;
	public double gamma;

	public DefaultExposureScheme(Viewpoint camera, int exposure, double gamma,
			int width, int height) {
		super();
		this.camera = camera;
		this.exposureFactor = exposure;
		this.exposures = new int[width][height];
		this.gamma = gamma;
	}

	public int exposureFactor;

	@Override
	public Color getColor(StrangePoint point) {
		Point location = camera.getCoords(point.point);

		try {
			exposures[location.x][location.y]++;
			int value = exposures[location.x][location.y];

			double brightness = (float) Math.pow(value, gamma) / exposureFactor;

			int R = (int) (initialColor.getRed() + brightness
					* (endpoint.getRed() - initialColor.getRed()));
			int G = (int) (initialColor.getGreen() + brightness
					* (endpoint.getGreen() - initialColor.getGreen()));
			int B = (int) (initialColor.getBlue() + brightness
					* (endpoint.getBlue() - initialColor.getBlue()));

			if (endpoint.getRed() >= initialColor.getRed()) {
				R = Math.min(R, endpoint.getRed());
			} else {
				R = Math.max(R, endpoint.getRed());
			}

			if (endpoint.getBlue() >= initialColor.getBlue()) {
				B = Math.min(B, endpoint.getBlue());
			} else {
				B = Math.max(B, endpoint.getBlue());
			}

			if (endpoint.getGreen() >= initialColor.getGreen()) {
				G = Math.min(G, endpoint.getGreen());
			} else {
				G = Math.max(G, endpoint.getGreen());
			}
			return new Color(R, G, B);
		} catch (ArrayIndexOutOfBoundsException e) {
			return Color.black;
		}
	}

	Viewpoint getCamera() {
		return camera;
	}

	void setCamera(Viewpoint camera) {
		this.camera = camera;
	}

	@Override
	public boolean overrides() {
		return true;
	}

}
